{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用LangChain构建应用程序"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### PDF问答程序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 安装tiktoken,PyPDF2,Faiss-GPU\n",
    "!pip -q install tiktoken PyPDF2 faiss-gpu"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入必要的库\n",
    "from PyPDF2 import PdfReader\n",
    "from langchain.embeddings.openai import OpenAIEmbeddings\n",
    "from langchain.text_splitter import CharacterTextSplitter\n",
    "from langchain.vectorstores import FAISS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 调用PdfReader类加载pdf文件\n",
    "doc_reader = PdfReader(\"./impromptu-rh.pdf\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用PdfReader类的extract_text()函数提取PDF中的文字\n",
    "raw_text = \"\"\n",
    "for i,page in enumerate(doc_reader.pages):\n",
    "    text = page.extract_text()\n",
    "    if text:\n",
    "        raw_text += text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用LangChain内置的ChartacterTextSplitter类对文本进行分割\n",
    "text_splitter = CharacterTextSplitter(\n",
    "    separator=\"\\n\",\n",
    "    chunk_size=1000,\n",
    "    chunk_overlap=200,\n",
    "    length_function = len\n",
    ")\n",
    "\n",
    "# 使用split_text()函数对文本进行分割\n",
    "texts = text_splitter.split_text(raw_text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 检查块数\n",
    "len(texts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 随机选择一个块进行检查\n",
    "import random \n",
    "\n",
    "texts[random.randint(0, len(texts))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载OpenAI嵌入\n",
    "embeddings = OpenAIEmbeddings()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建PDF的向量存储库\n",
    "docsearch = FAISS.from_texts(texts,embeddings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 执行搜索\n",
    "query = \"GPT-4 如何改变了社交媒体？\"\n",
    "docs = docsearch.similarity_search(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "len(docs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "docs[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 创建问答链"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载LLM和QA链\n",
    "from langchain.chains.question_answering import load_qa_chain\n",
    "from langchain.llms import OpenAI\n",
    "chain = load_qa_chain(\n",
    "    OpenAI(),\n",
    "    chain_type = \"stuff\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 执行QA链\n",
    "query = \"这本书的作者是谁？\"\n",
    "docs = docsearch.similarity_search(query)\n",
    "\n",
    "chain.run(input_documents=docs, question=query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 重新设置topk来获得更多的答案\n",
    "docs = docsearch.similarity_search(query, k=6)\n",
    "chain.run(input_documents=docs, question=query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 重新构建一个重排链\n",
    "from langchain.chains.question_answering import load_qa_chain\n",
    "\n",
    "chain = load_qa_chain(\n",
    "    OpenAI(),\n",
    "    chain_type = \"map_rerank\",\n",
    "    return_intermediate_steps = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 执行QA链\n",
    "query = \"OpenAI的创始人是谁？\"\n",
    "docs = docsearch.similarity_search(query,k=10)\n",
    "results = chain(\n",
    "    {\"input_documents\":docs, \"question\":query},\n",
    "    return_only_outputs = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 打印最终答案\n",
    "results[\"output_text\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 检查LLM链的提示词模板\n",
    "chain.llm_chain.prompt.template"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建一个检索QA链\n",
    "docsearch = FAISS.from_texts(texts, embeddings)\n",
    "\n",
    "from langchain.chains import RetrievalQA\n",
    "\n",
    "retriever = docsearch.as_retriever(search_type=\"similarity\",search_kwargs={\"k\":4})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建QA链\n",
    "rqa = RetrievalQA.from_chain_type(\n",
    "    llm = OpenAI(),\n",
    "    chain_type = \"stuff\",\n",
    "    retriever = retriever,\n",
    "    return_source_documents = True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 执行查询\n",
    "query = \"OpenAI 是什么？\"\n",
    "rqa(query)['result']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "query = \"GPT-4 对创新力有什么影响？\"\n",
    "rqa(query)['result']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 对话式表单"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### OpenAI函数的标记链"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.chains import LLMChain\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "from pydantic import BaseModel,Field\n",
    "from enum import Enum\n",
    "from langchain.chains.openai_functions import (\n",
    "    create_tagging_chain,\n",
    "    create_tagging_chain_pydantic\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义个人数据模型\n",
    "class PersonalDetails(BaseModel):\n",
    "    # 定义数据类型\n",
    "    name:str = Field(\n",
    "        ...,\n",
    "        description=\"这是用户输入的名字\"\n",
    "    )\n",
    "    city:str = Field(\n",
    "        ...,\n",
    "        description=\"这是用户输入的城市\"\n",
    "    )\n",
    "    email:str = Field(\n",
    "        ...,\n",
    "        description=\"这是用户输入的邮箱地址\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建聊天LLM\n",
    "llm = ChatOpenAI(temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建标记链\n",
    "chain = create_tagging_chain_pydantic(PersonalDetails,llm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运行链\n",
    "test_input = \"你好，我叫大霖，我住在辽宁沈阳，我的邮箱是：876251324@xxx.com\"\n",
    "test_result = chain.run(test_input)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 运行一个信息并不全面的输入\n",
    "test_str = \"我的电子邮箱地址是：876251324@xxx.com\"\n",
    "test_result = chain.run(test_str)\n",
    "\n",
    "test_result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 创建提示词模板"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ask_for_info(ask_for=[\"name\",\"city\",\"email\"]):\n",
    "    # 定义一个提示词模板\n",
    "    first_prompt = ChatPromptTemplate.from_template(\n",
    "        \"\"\"\n",
    "        假设你现在是一名前台，你现在需要对用户进行询问他个人的具体信息。\n",
    "        不要跟用户打招呼！你可以解释你需要什么信息。不要说“你好！”！\n",
    "        接下来你和用户之间的对话都是你来提问，凡是你说的都是问句。\n",
    "        你每次随机选择{ask_for}列表中的一个项目，向用户提问。\n",
    "        比如{\"name\",\"city\"}列表，你可以随机选择一个\"name\"，\n",
    "        你的问题是：“请问你的名字是什么？”\n",
    "        \"\"\"\n",
    "    )\n",
    "\n",
    "    info_gathering_chain = LLMChain(llm=llm,prompt=first_prompt)\n",
    "    chat_chain = info_gathering_chain.run(ask_for=ask_for)\n",
    "\n",
    "    return chat_chain"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据更新和检查"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义检查字段为空的函数\n",
    "def check_what_is_empty(user_personal_details):\n",
    "    ask_for = []\n",
    "    # 检查项目是否为空\n",
    "    for field,value in user_personal_details.dict().items():\n",
    "        if value in [None,\"\",0]:\n",
    "            print(f\"{field}为空\")\n",
    "            ask_for.append(field)\n",
    "    return ask_for"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "user_007_personal_details = PersonalDetails(name=\"\",city=\"\",email=\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ask_for = check_what_is_empty(user_007_personal_details)\n",
    "ask_for"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义add_non_empty_details函数负责更新用户的信息\n",
    "def add_non_empty_details(current_details:PersonalDetails,new_details:PersonalDetails):\n",
    "    # 这是已经填好的用户信息\n",
    "    non_empty_details = {k:v for k,v in new_details.dict().items() if v not in [None,\"\",0]}\n",
    "    update_details = current_details.copy(update=non_empty_details)\n",
    "    return update_details"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "res = chain.run(\"我的名字007\")\n",
    "user_007_personal_details = add_non_empty_details(user_007_personal_details,res)\n",
    "user_007_personal_details"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ask_for = check_what_is_empty(user_007_personal_details)\n",
    "ask_for"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 构建BabyAGI"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入工具\n",
    "import os\n",
    "from collections import deque\n",
    "from typing import Dict,List,Optional,Any\n",
    "from langchain import LLMChain,OpenAI,PromptTemplate\n",
    "from langchain.embeddings import OpenAIEmbeddings\n",
    "from langchain.llms import BaseLLM\n",
    "from langchain.vectorstores.base import VectorStore\n",
    "from pydantic import BaseModel,Field\n",
    "from langchain.chains.base import Chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入FAISS\n",
    "from langchain.vectorstores import FAISS\n",
    "from langchain.docstore import InMemoryDocstore"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.embeddings.openai.OpenAIEmbeddings` was deprecated in langchain-community 0.0.9 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import OpenAIEmbeddings`.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 创建嵌入模型\n",
    "embeddings = OpenAIEmbeddings()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化向量数据库\n",
    "import faiss\n",
    "embedding_size = 1536\n",
    "index = faiss.IndexFlatL2(embedding_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "`embedding_function` is expected to be an Embeddings object, support for passing in a function will soon be removed.\n"
     ]
    }
   ],
   "source": [
    "# 将生成的向量和构建的索引进行存储\n",
    "vectorstore = FAISS(\n",
    "    embeddings.embed_query,\n",
    "    index,\n",
    "    InMemoryDocstore({}),\n",
    "    {}\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义创建任务链\n",
    "class TaskCreationChain(LLMChain):\n",
    "\n",
    "    @classmethod\n",
    "    def from_llm(cls,llm:BaseLLM,verbose:bool=True) -> LLMChain:\n",
    "        # 从解析器获得响应\n",
    "        task_creation_template = (\n",
    "            \"You are an task creation AI that uses the result of an execution agent\"\n",
    "            \" to create new tasks with the following objective:{objective},\"\n",
    "            \" The last completed task has the result:{result}.\"\n",
    "            \" This result was based on this task description:{task_description}.\"\n",
    "            \" These are incomplete tasks: {incomplete_tasks}.\"\n",
    "            \" Based on the result,create new tasks to be completed\"\n",
    "            \" by the AI system that do not overlap with incomplete tasks.\"\n",
    "            \" Return the tasks as an array.\"\n",
    "        )\n",
    "        prompt = PromptTemplate(\n",
    "            template = task_creation_template,\n",
    "            input_variables = [\"result\",\"task_description\",\"incomplete_tasks\",\"objective\"],\n",
    "        )\n",
    "        return cls(llm=llm,prompt=prompt,verbose=verbose)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建任务优先级判断链\n",
    "class TaskPrioritizationChain(LLMChain):\n",
    "    \n",
    "    @classmethod\n",
    "    def from_llm(cls,llm:BaseLLM,verbose:bool=True) -> LLMChain:\n",
    "        # 从解析器获得响应\n",
    "        task_prioritization_template = (\n",
    "            \"You are an task prioritization AI tasked with cleaning the fromatting of and reprioritizing\"\n",
    "            \" the following tasks: {task_names}.\"\n",
    "            \" Consider the ultimate objective of your team : {objective}.\"\n",
    "            \" Do not remove any tasks.Return the result as a numbered list,like:\"\n",
    "            \" #. First task\"\n",
    "            \" #. Second task\"\n",
    "            \" Start the task list with number {next_task_id}.\"\n",
    "        )\n",
    "        prompt = PromptTemplate(\n",
    "            template = task_prioritization_template,\n",
    "            input_variables = [\"task_names\",\"objective\",\"next_task_id\"],\n",
    "        )\n",
    "\n",
    "        return cls(llm=llm,prompt=prompt,verbose=verbose)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain_community.llms.openai.OpenAI` was deprecated in langchain-community 0.0.10 and will be removed in 0.2.0. An updated version of the class exists in the langchain-openai package and should be used instead. To use it run `pip install -U langchain-openai` and import as `from langchain_openai import OpenAI`.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 执行链\n",
    "from langchain.agents import ZeroShotAgent,Tool,AgentExecutor\n",
    "from langchain import OpenAI,SerpAPIWrapper,LLMChain\n",
    "\n",
    "todo_prompt = PromptTemplate.from_template(\n",
    "    \"You are planner who is an expert at coming up with a todo list for a given objective.Come up with a todo list for this objective: {objective}\")\n",
    "\n",
    "todo_chain = LLMChain(llm=OpenAI(),prompt=todo_prompt)\n",
    "\n",
    "search = SerpAPIWrapper()\n",
    "\n",
    "tools = [\n",
    "    Tool(\n",
    "        name = \"Search\",\n",
    "        func = search.run,\n",
    "        description = \"useful for when you need to answer questions about current events\"\n",
    "    ),\n",
    "    Tool(\n",
    "        name = \"TODO\",\n",
    "        func = todo_chain.run,\n",
    "        description = \"useful for when you need to come up with todo lists.Input:an objective to create a todo list for.Output:a todo list for that objective.Please be very clear what the objective is!\"\n",
    "    )\n",
    "]\n",
    "\n",
    "prefix = \"\"\"You are an AI who performs one task based on the following \n",
    "objective: {objective}.Take into account these previously these previously completed\n",
    "tasks: {context}.\n",
    "\"\"\"\n",
    "\n",
    "suffix = \"\"\"\n",
    "Question: {task}\n",
    "{agent_scratchpad}\n",
    "\"\"\"\n",
    "\n",
    "prompt = ZeroShotAgent.create_prompt(\n",
    "    tools,\n",
    "    prefix = prefix,\n",
    "    suffix = suffix,\n",
    "    input_variables = [\"objective\",\"context\",\"task\",\"agent_scratchpad\"],\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 整合所有链\n",
    "def get_next_task(\n",
    "        task_createion_chain:LLMChain,\n",
    "        result:Dict,\n",
    "        task_description:str,\n",
    "        task_list:List[str],\n",
    "        objective:str\n",
    "    ) -> List[Dict]:\n",
    "    # 获取下个任务\n",
    "    incomplete_tasks = \", \".join(task_list)\n",
    "    response = task_createion_chain.run(\n",
    "        result = result,\n",
    "        task_description = task_description,\n",
    "        incomplete_tasks = incomplete_tasks,\n",
    "        objective = objective\n",
    "    )\n",
    "    new_tasks = response.split(\"\\n\")\n",
    "    return [{\"task_name\":task_name} for task_name in new_tasks if task_name.strip()]\n",
    "\n",
    "# 定义任务优先级函数\n",
    "def prioritize_tasks(task_prioritization_chain:LLMChain,this_task_id:int,task_list:List[str],objective:str) -> List[str]:\n",
    "    task_names = [t[\"task_name\"] for t in task_list]\n",
    "    next_task_id = int(this_task_id) + 1\n",
    "    response = task_prioritization_chain.run(\n",
    "        task_names = task_names,\n",
    "        next_task_id = next_task_id,\n",
    "        objective = objective\n",
    "    )\n",
    "    new_tasks = response.split(\"\\n\")\n",
    "    prioritized_tasks_list = []\n",
    "    for task_string in new_tasks:\n",
    "        if not task_string.strip():\n",
    "            continue\n",
    "        task_parts = task_string.strip().split(\".\",1)\n",
    "        if len(task_parts) == 2:\n",
    "            task_id = task_parts[0].strip()\n",
    "            task_name = task_parts[1].strip()\n",
    "            prioritized_tasks_list.append(\n",
    "                {\n",
    "                    \"task_id\":task_id,\n",
    "                    \"task_name\":task_name\n",
    "                }\n",
    "            )\n",
    "    return prioritized_tasks_list\n",
    "\n",
    "# 获取获取最优先的K个任务函数\n",
    "def _get_top_tasks(vectorstore,query:str,k:int) -> List[str]:\n",
    "    results = vectorstore.similarity_search_with_score(query,k=k)\n",
    "    if not results:\n",
    "        return []\n",
    "    \n",
    "    sorted_results,_ = zip(*sorted(results,key=lambda x:x[1],reverse=True))\n",
    "\n",
    "    return [str(item.metadata['task']) for item in sorted_results]\n",
    "\n",
    "# 定义执行任务函数\n",
    "def execute_task(vectorstore,execution_chain:LLMChain,objective:str,task:str,k:int = 5) -> str:\n",
    "    context = _get_top_tasks(vectorstore,query=objective,k=k)\n",
    "    return execution_chain.run(\n",
    "        objective = objective,\n",
    "        context = context,\n",
    "        task = task\n",
    "    )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建BabyAGI类\n",
    "class BabyAGI(Chain,BaseModel):\n",
    "    # 用于BabyAGI智能体的控制模型\n",
    "    \n",
    "    task_list:deque = Field(default_factory=deque)\n",
    "    task_creation_chain:TaskCreationChain = Field(...)\n",
    "    task_prioritization_chain:TaskPrioritizationChain = Field(...)\n",
    "    execution_chain:AgentExecutor = Field(...)\n",
    "    task_id_counter:int = Field(1)\n",
    "    vectorstore:VectorStore = Field(init=False)\n",
    "    max_iterations: Optional[int] = None\n",
    "\n",
    "    class config:\n",
    "        # 用于配置BabyAGI智能体的参数\n",
    "\n",
    "        aribtray_types_allowed = True\n",
    "\n",
    "    def add_task(self,task:Dict):\n",
    "        self.task_list.append(task)\n",
    "\n",
    "    def print_task_list(self):\n",
    "        print(\"\\033[95m\\033[1m\" + \"\\n*TASK LIST*\\n\" + \"\\033[0m\\033[0m\")\n",
    "        for task in self.task_list:\n",
    "            print(str(task[\"task_id\"]) + \": \" + task[\"task_name\"])\n",
    "        \n",
    "    def print_next_task(self,task:Dict):\n",
    "        print(\"\\033[92m\\033[1m\" + \"\\n*NEXT TASK*\\n\" + \"\\033[0m\\033[0m\")\n",
    "        print(str(task[\"task_id\"]) + \": \" + task[\"task_name\"])\n",
    "\n",
    "    def print_task_result(self,result:str):\n",
    "        print(\"\\033[93m\\033[1m\" + \"\\n*RESULT*\\n\" + \"\\033[0m\\033[0m\")\n",
    "        print(result)\n",
    "\n",
    "    @property\n",
    "    def input_keys(self) -> List[str]:\n",
    "        return [\"objective\"]\n",
    "    \n",
    "    @property\n",
    "    def output_keys(self) -> List[str]:\n",
    "        return []\n",
    "\n",
    "    def _call(self,inputs:Dict[str,Any]) -> Dict[str,Any]:\n",
    "        # 执行BabyAGI智能体\n",
    "        objective = inputs[\"objective\"]\n",
    "        first_task = inputs.get(\"first_task\",\"Make a todo list\")\n",
    "        self.add_task({\"task_id\":1,\"task_name\":first_task})\n",
    "        num_iters = 0\n",
    "        while True:\n",
    "            if self.task_list:\n",
    "                self.print_task_list()\n",
    "                # 第一步：拉取第一个任务\n",
    "                task = self.task_list.popleft()\n",
    "                \n",
    "                # 第二步：执行任务\n",
    "                result = execute_task(\n",
    "                    self.vectorstore,\n",
    "                    self.execution_chain,\n",
    "                    objective,\n",
    "                    task[\"task_name\"]\n",
    "                )\n",
    "                this_task_id = int(task[\"task_id\"])\n",
    "                self.print_task_result(result)\n",
    "\n",
    "                # 存储结果\n",
    "                result_id = f\"result_{this_task_id}\"\n",
    "                self.vectorstore.add_texts(\n",
    "                    texts = [result],\n",
    "                    metadata = [{\"task\":task[\"task_name\"]}],\n",
    "                    ids = [result_id]\n",
    "                )\n",
    "\n",
    "                # 第四步：执行新任务并重新调整任务列表的优先级\n",
    "                new_tasks = get_next_task(\n",
    "                    self.task_creation_chain,\n",
    "                    result = result,\n",
    "                    task_description = task[\"task_name\"],\n",
    "                    task_list = [t[\"task_name\"] for t in self.task_list],\n",
    "                    objective = objective\n",
    "                )\n",
    "\n",
    "                for new_task in new_tasks:\n",
    "                    self.task_id_counter += 1\n",
    "                    new_task.update({\"task_id\":self.task_id_counter})\n",
    "                    self.add_task(new_task)\n",
    "                    self.task_list = deque(\n",
    "                        prioritize_tasks(\n",
    "                            self.task_prioritization_chain,\n",
    "                            this_task_id,\n",
    "                            list(self.task_list),\n",
    "                            objective\n",
    "                        )\n",
    "                    )\n",
    "                num_iters += 1\n",
    "                if self.max_iterations is not None and num_iters == self.max_iterations:\n",
    "                    print(f\"\\033[91m\\033[1m\" + \"\\n*TASK ENDING*\\n\" + \"\\033[0m\\033[0m\")\n",
    "                    break\n",
    "        return {}\n",
    "\n",
    "    @classmethod\n",
    "    def from_llm(\n",
    "        cls,\n",
    "        llm: BaseLLM,\n",
    "        vectorstore: VectorStore,\n",
    "        verbose: bool = False,\n",
    "        **kwargs\n",
    "    ) -> \"BabyAGI\":\n",
    "        # 初始化BabyAGI控制器\n",
    "        task_creation_chain = TaskCreationChain.from_llm(llm,verbose=verbose)\n",
    "        task_prioritization_chain = TaskPrioritizationChain.from_llm(llm,verbose=verbose)\n",
    "        llm_chain = LLMChain(llm=llm,prompt=prompt)\n",
    "        tool_names = [tool.name for tool in tools]\n",
    "        agent = ZeroShotAgent(llm_chain=llm_chain,allowed_tools=tool_names)\n",
    "        agent_executor = AgentExecutor.from_agent_and_tools(\n",
    "            agent = agent,\n",
    "            tools = tools,\n",
    "            verbose = True\n",
    "        )\n",
    "        return cls(\n",
    "            task_creation_chain = task_creation_chain,\n",
    "            task_prioritization_chain = task_prioritization_chain,\n",
    "            execution_chain = agent_executor,\n",
    "            vectorstore = vectorstore,\n",
    "            **kwargs\n",
    "        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化LLM\n",
    "llm = OpenAI(temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化OBJECTIVE\n",
    "OBJECTIVE = \"Find the cheapest price and site to buy a Yubikey 5c online and give me the URL\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The class `langchain.agents.mrkl.base.ZeroShotAgent` was deprecated in langchain 0.1.0 and will be removed in 0.2.0. Use create_react_agent instead.\n",
      "  warn_deprecated(\n"
     ]
    }
   ],
   "source": [
    "# 初始化LLMChains\n",
    "verbose = False\n",
    "# 如果为空，则将继续执行\n",
    "max_iterations:Optional[int] = 7\n",
    "# 实例化BabyAGI\n",
    "baby_agi = BabyAGI.from_llm(\n",
    "    llm = llm,\n",
    "    vectorstore = vectorstore,\n",
    "    verbose = verbose,\n",
    "    max_iterations = max_iterations\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `__call__` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[95m\u001b[1m\n",
      "*TASK LIST*\n",
      "\u001b[0m\u001b[0m\n",
      "1: Make a todo list\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/elin/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:117: LangChainDeprecationWarning: The function `run` was deprecated in LangChain 0.1.0 and will be removed in 0.2.0. Use invoke instead.\n",
      "  warn_deprecated(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: I should think about what tasks need to be included in the todo list\n",
      "Action: TODO\n",
      "Action Input: Objective to create a todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Define the purpose and scope of the todo list: Decide what tasks and goals the list should cover and how detailed it needs to be.\n",
      "\n",
      "2. Brainstorm and list all tasks: Start by brainstorming all the tasks that need to be done in order to create the todo list. This could include research, organizing, and prioritizing.\n",
      "\n",
      "3. Categorize tasks: Group similar tasks together to make them easier to manage. This could include categories such as research, planning, and implementation.\n",
      "\n",
      "4. Prioritize tasks: Determine which tasks are the most important and should be done first. This will help to ensure that the most crucial items are completed first.\n",
      "\n",
      "5. Set deadlines: Assign a deadline to each task to ensure that the todo list is completed in a timely manner. Be realistic with the deadlines and leave some buffer time for unexpected delays.\n",
      "\n",
      "6. Assign responsibilities: If you are working with a team, assign specific tasks to each team member to ensure accountability and efficient completion of the todo list.\n",
      "\n",
      "7. Break down larger tasks: If there are any tasks that seem too big or overwhelming, break them down into smaller, more manageable tasks.\n",
      "\n",
      "8. Create a schedule: Using the deadlines and priorities, create a schedule for completing each task. This will help to\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should review the todo list and make sure all necessary tasks are included and organized in a logical manner.\n",
      "Action: TODO\n",
      "Action Input: Review the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Start by reviewing the current todo list and identify any tasks that have been completed.\n",
      "2. Prioritize the remaining tasks based on urgency and importance.\n",
      "3. Determine if any new tasks need to be added to the list.\n",
      "4. Delegate any tasks that can be completed by someone else.\n",
      "5. Set a realistic timeline for completing the remaining tasks.\n",
      "6. Break down larger tasks into smaller, more manageable subtasks.\n",
      "7. Set reminders or deadlines for each task to ensure they are completed on time.\n",
      "8. Consider any potential obstacles or challenges that may arise and come up with contingency plans.\n",
      "9. Take breaks throughout the day to avoid burnout and maintain productivity.\n",
      "10. Regularly review and update the todo list as needed. \n",
      "\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should make sure the todo list is easily accessible and can be updated as needed.\n",
      "Action: TODO\n",
      "Action Input: Make the todo list easily accessible\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Define the objective: The first step is to clearly define the objective of making the todo list easily accessible. This will help guide the rest of the planning process.\n",
      "\n",
      "2. Identify the target audience: Who needs to access the todo list? Is it just for yourself or for a team? This will help determine the best way to make it easily accessible for everyone involved.\n",
      "\n",
      "3. Choose a digital platform: There are many digital platforms available for creating and managing todo lists, such as Trello, Asana, or Google Keep. Choose one that is user-friendly and can be easily accessed by all members of the team.\n",
      "\n",
      "4. Set up a shared account: If the todo list is for a team, consider setting up a shared account on the chosen platform so that everyone has access to it.\n",
      "\n",
      "5. Create a naming convention: To make it easy to find and access the todo list, come up with a consistent naming convention for the list. This could include the project name, date, or team members' names.\n",
      "\n",
      "6. Organize tasks into categories: Categorizing tasks can make it easier to find and prioritize them. Consider organizing tasks by project, deadline, or priority level.\n",
      "\n",
      "7. Utilize color-coding: Color-coding tasks can also help with\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should regularly review and update the todo list to ensure it remains relevant and effective.\n",
      "Action: TODO\n",
      "Action Input: Review and update the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Evaluate current todo list: Take a look at your current todo list and assess its completeness and accuracy. Note down any tasks that have been completed and any that still need to be done.\n",
      "\n",
      "2. Prioritize tasks: Prioritize the tasks on your todo list based on urgency and importance. This will help you focus on what needs to be done first.\n",
      "\n",
      "3. Break down larger tasks: If you have any large or daunting tasks on your todo list, break them down into smaller, more manageable tasks. This will make it easier to tackle them and feel a sense of accomplishment as you complete each smaller task.\n",
      "\n",
      "4. Add new tasks: Take a look at your calendar and schedule for the upcoming days and weeks. Are there any new tasks that need to be added to your todo list? Be sure to add them in and prioritize them accordingly.\n",
      "\n",
      "5. Remove or delegate unnecessary tasks: Sometimes, tasks on your todo list may no longer be relevant or can be delegated to someone else. Review your list and see if there are any tasks that can be removed or delegated to free up your time.\n",
      "\n",
      "6. Set deadlines: Assign deadlines to each task on your todo list. This will help you stay on track and ensure that tasks are completed in a timely manner.\n",
      "\n",
      "7.\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should regularly review and update the todo list to ensure it remains relevant and effective.\n",
      "Action: TODO\n",
      "Action Input: Review and update the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Start by reviewing the current todo list to get an understanding of what tasks have already been completed and what still needs to be done.\n",
      "\n",
      "2. Take note of any tasks that are no longer relevant or can be removed from the list.\n",
      "\n",
      "3. Prioritize the remaining tasks based on urgency and importance.\n",
      "\n",
      "4. Break down larger tasks into smaller, more manageable sub-tasks.\n",
      "\n",
      "5. Set realistic deadlines for each task to ensure timely completion.\n",
      "\n",
      "6. Determine the resources needed for each task, such as time, budget, and team members.\n",
      "\n",
      "7. Delegate tasks to team members if necessary, ensuring that everyone is aware of their responsibilities and deadlines.\n",
      "\n",
      "8. Create a schedule or timeline for completing the tasks, taking into account any dependencies or necessary approvals.\n",
      "\n",
      "9. Use a task management tool or app to keep track of the tasks and their progress.\n",
      "\n",
      "10. Regularly review and update the todo list as new tasks or changes arise.\n",
      "\n",
      "11. Communicate any updates or changes to the team to ensure everyone is on the same page.\n",
      "\n",
      "12. Celebrate and acknowledge progress and completion of tasks to keep motivation high.\n",
      "\n",
      "13. Continuously reassess and reprioritize tasks as needed to ensure the most important and urgent tasks are being completed.\n",
      "\n",
      "14. Reflect on the process and\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should make sure the todo list is easily accessible and can be updated as needed.\n",
      "Action: TODO\n",
      "Action Input: Make the todo list easily accessible\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Determine the purpose of the todo list: Before creating the list, it is important to understand the main objective of having an easily accessible todo list. Is it for personal use or for a team? Will it be used for daily tasks or for long-term projects? This will help in tailoring the list to fit specific needs.\n",
      "\n",
      "2. Choose a platform: There are various platforms available for creating and organizing todo lists, such as digital apps, physical planners, or online tools. Consider the features and accessibility of each platform and choose one that suits the purpose and preferences of the user.\n",
      "\n",
      "3. Identify essential tasks: Brainstorm and list down all the tasks that need to be included in the todo list. This could include daily tasks, deadlines, appointments, meetings, or reminders.\n",
      "\n",
      "4. Categorize tasks: Group similar tasks together to create a more organized and user-friendly list. This could be done based on the type of task (personal vs. work), priority level, or due date.\n",
      "\n",
      "5. Set reminders: To ensure that tasks are not forgotten, it is important to set reminders for each task. This could be done through the chosen platform, such as setting notifications on a digital app or setting alarms on a physical planner.\n",
      "\n",
      "6. Add details: For\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should make sure the todo list is easily accessible and can be updated as needed.\n",
      "Action: TODO\n",
      "Action Input: Make the todo list easily accessible\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Determine the scope and purpose of the todo list: Before creating the list, it's important to clearly define what the list will be used for and who will have access to it. This will help guide the creation process and ensure that the list is easily accessible to the right people.\n",
      "\n",
      "2. Choose a platform or tool: There are many options for creating and organizing a todo list, including physical planners, digital apps, and online platforms. Consider the needs and preferences of the users and choose a platform that is easy to use and can be accessed from multiple devices.\n",
      "\n",
      "3. Create categories or sections: To make the list more organized and user-friendly, consider dividing it into different categories or sections. This could be based on priority, type of task, or even different team members. This will make it easier for users to find and focus on specific tasks.\n",
      "\n",
      "4. Use color-coding or labels: Adding color-coding or labels to the tasks can help users quickly identify the status or type of task. For example, red could represent urgent tasks, blue could represent completed tasks, etc. This will make it easier for users to prioritize and track their progress.\n",
      "\n",
      "5. Include due dates and reminders: To ensure that tasks are completed on time, it's important to include\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should regularly review and update the todo list to ensure it remains relevant and effective.\n",
      "Action: TODO\n",
      "Action Input: Review and update the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Start by reviewing the current todo list to see what tasks have already been completed and what still needs to be done.\n",
      "\n",
      "2. Prioritize tasks based on urgency and importance, and make necessary adjustments to the current list.\n",
      "\n",
      "3. Identify any tasks that are no longer relevant or necessary and remove them from the list.\n",
      "\n",
      "4. Add any new tasks that need to be completed to the list.\n",
      "\n",
      "5. Break down larger tasks into smaller, more manageable subtasks.\n",
      "\n",
      "6. Set realistic deadlines for each task and add them to the list.\n",
      "\n",
      "7. Assign tasks to team members or yourself, if working alone.\n",
      "\n",
      "8. Make sure all tasks are clearly defined and have a specific action plan.\n",
      "\n",
      "9. Consider any potential obstacles or challenges that may arise and come up with solutions beforehand.\n",
      "\n",
      "10. Regularly review and update the list as tasks are completed or new ones arise.\n",
      "\n",
      "11. Communicate any changes or updates to team members or stakeholders.\n",
      "\n",
      "12. Stay organized by using a task management tool or system to keep track of the list.\n",
      "\n",
      "13. Celebrate and acknowledge progress and completion of tasks.\n",
      "\n",
      "14. Reflect on the effectiveness of the current todo list and make necessary improvements for future planning.\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should make sure the todo list is easily accessible and can be updated as needed.\n",
      "Action: TODO\n",
      "Action Input: Make the todo list easily accessible\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "Todo List for Making Todo List Easily Accessible:\n",
      "\n",
      "1. Identify the objective: The first step in creating a todo list for making the todo list easily accessible is to clearly define the objective. This will help determine the specific tasks and steps needed to achieve the goal.\n",
      "\n",
      "2. Determine target audience: Who will be using the todo list? Is it for personal use or for a team? Identifying the target audience will help in designing the todo list to best suit their needs.\n",
      "\n",
      "3. Choose a platform: Decide on a platform or tool to create and store the todo list. There are many options available such as physical planners, digital apps, or even a simple pen and paper.\n",
      "\n",
      "4. List the essential tasks: Make a list of all the necessary tasks needed to make the todo list easily accessible. This could include creating categories, setting reminders, or sharing the list with others.\n",
      "\n",
      "5. Prioritize tasks: Prioritize the tasks based on their importance and urgency. This will help in creating a more efficient and effective plan of action.\n",
      "\n",
      "6. Set a timeline: Determine a realistic timeline for completing each task. This will help in staying on track and meeting the overall objective.\n",
      "\n",
      "7. Consider accessibility features: If the todo list is for a team, consider adding accessibility features such\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should make sure the todo list is easily accessible and can be updated as needed.\n",
      "Action: TODO\n",
      "Action Input: Make the todo list easily accessible\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Define the objective: The first step is to clearly define the objective of making the todo list easily accessible. This will help in setting a specific goal and creating a targeted plan.\n",
      "\n",
      "2. Choose a platform: Decide on a platform or tool that will house the todo list. This could be a physical planner, a digital app, or even a simple notepad.\n",
      "\n",
      "3. Set up a system: Create a system for organizing and updating the todo list. This could include color-coding, categorizing tasks, or setting deadlines.\n",
      "\n",
      "4. Prioritize tasks: Identify the most important and urgent tasks and prioritize them accordingly. This will help in effectively managing time and completing tasks in a timely manner.\n",
      "\n",
      "5. Include all relevant tasks: Make sure to include all tasks, big or small, that need to be completed in the todo list. This will ensure that nothing important is left out.\n",
      "\n",
      "6. Break down larger tasks: If there are any larger tasks that seem overwhelming, break them down into smaller, more manageable tasks. This will make them less daunting and easier to tackle.\n",
      "\n",
      "7. Set reminders: Utilize the reminder feature on the chosen platform to stay on top of tasks and deadlines. This will help in keeping the todo list up-to-date and easily accessible.\n",
      "\n",
      "8\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should regularly review and update the todo list to ensure it remains relevant and effective.\n",
      "Action: TODO\n",
      "Action Input: Review and update the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Assess the current todo list: Before making any updates, it is important to review the existing todo list to get a clear understanding of the tasks that need to be completed. This will help in prioritizing and organizing the tasks effectively.\n",
      "\n",
      "2. Identify any incomplete or pending tasks: Look through the todo list and identify any tasks that have not been completed or are still pending. This will help in determining which tasks need immediate attention and can be included in the updated todo list.\n",
      "\n",
      "3. Prioritize tasks: Based on the urgency and importance of each task, prioritize them accordingly. This will help in ensuring that the most critical tasks are completed first.\n",
      "\n",
      "4. Break down big tasks into smaller ones: If there are any tasks that seem overwhelming or too big to tackle, break them down into smaller, more manageable tasks. This will make it easier to track progress and stay motivated.\n",
      "\n",
      "5. Set realistic deadlines: Assign a realistic deadline to each task based on its complexity and priority. This will help in staying on track and ensuring that the tasks are completed within a reasonable time frame.\n",
      "\n",
      "6. Delegate tasks: If there are tasks that can be delegated to others, assign them to appropriate team members. This will help in sharing the workload and getting tasks done more efficiently.\n",
      "\n",
      "7.\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI should regularly review and update the todo list to ensure it remains relevant and effective.\n",
      "Action: TODO\n",
      "Action Input: Review and update the todo list\u001b[0m\n",
      "Observation: \u001b[33;1m\u001b[1;3m\n",
      "\n",
      "1. Start by reviewing the current todo list to get an idea of what tasks need to be completed.\n",
      "2. Prioritize the tasks based on urgency and importance.\n",
      "3. Identify any incomplete or overdue tasks and determine the reason for their delay.\n",
      "4. Make a separate list of tasks that need to be added or updated.\n",
      "5. Set a realistic timeline for completing the tasks.\n",
      "6. Break down larger tasks into smaller, actionable steps.\n",
      "7. Delegate tasks to team members or seek assistance if needed.\n",
      "8. Set reminders or deadlines for each task to ensure timely completion.\n",
      "9. Regularly check and update the progress of each task.\n",
      "10. Once all tasks are completed, review and update the overall todo list to reflect the changes.\n",
      "11. Reflect on the effectiveness of the previous todo list and make any necessary adjustments for future planning.\n",
      "12. Celebrate the completion of the updated todo list and the progress made towards the objective.\u001b[0m\n",
      "Thought:\u001b[32;1m\u001b[1;3mI now know the final answer\n",
      "Final Answer: The final answer is a comprehensive and organized todo list that is easily accessible and can be regularly reviewed and updated to ensure its relevance and effectiveness.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "\u001b[93m\u001b[1m\n",
      "*RESULT*\n",
      "\u001b[0m\u001b[0m\n",
      "The final answer is a comprehensive and organized todo list that is easily accessible and can be regularly reviewed and updated to ensure its relevance and effectiveness.\n",
      "\u001b[95m\u001b[1m\n",
      "*TASK LIST*\n",
      "\u001b[0m\u001b[0m\n",
      "1: Check for any ongoing sales or discounts on Yubikey 5c.\n",
      "2: Research different online retailers that sell Yubikey 5c.\n",
      "3: Read reviews and ratings of the online retailers selling Yubikey 5c.\n",
      "4: Verify the authenticity and reliability of the online retailers.\n",
      "5: Check for the availability of Yubikey 5c on each online retailer.\n",
      "6: Consider the shipping and delivery options of each online retailer.\n",
      "7: Look for any additional fees or taxes that may affect the final price.\n",
      "8: Compare prices of Yubikey 5c on different online retailers.\n",
      "9: Prioritize online retailers with the lowest overall cost for Yubikey 5c.\n",
      "10: Compare prices and shipping fees for each retailer.\n",
      "11: Create a spreadsheet to organize the data.\n",
      "12: Identify the cheapest retailer for the Yubikey 5c.\n",
      "13: Check the availability of the Yubikey 5c on the chosen retailer's website.\n",
      "14: Provide the URL of the online retailer with the cheapest price for Yubikey 5c.\n",
      "15: Create an account on the retailer's website if necessary.\n",
      "16: Add the Yubikey 5c to the cart.\n",
      "17: Check for any available discount\n"
     ]
    },
    {
     "ename": "KeyError",
     "evalue": "'task'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[14], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mbaby_agi\u001b[49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mobjective\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43mOBJECTIVE\u001b[49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain_core/_api/deprecation.py:145\u001b[0m, in \u001b[0;36mdeprecated.<locals>.deprecate.<locals>.warning_emitting_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m    143\u001b[0m     warned \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m    144\u001b[0m     emit_warning()\n\u001b[0;32m--> 145\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mwrapped\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain/chains/base.py:378\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks, tags, metadata, run_name, include_run_info)\u001b[0m\n\u001b[1;32m    346\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Execute the chain.\u001b[39;00m\n\u001b[1;32m    347\u001b[0m \n\u001b[1;32m    348\u001b[0m \u001b[38;5;124;03mArgs:\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    369\u001b[0m \u001b[38;5;124;03m        `Chain.output_keys`.\u001b[39;00m\n\u001b[1;32m    370\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m    371\u001b[0m config \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m    372\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcallbacks\u001b[39m\u001b[38;5;124m\"\u001b[39m: callbacks,\n\u001b[1;32m    373\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtags\u001b[39m\u001b[38;5;124m\"\u001b[39m: tags,\n\u001b[1;32m    374\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmetadata\u001b[39m\u001b[38;5;124m\"\u001b[39m: metadata,\n\u001b[1;32m    375\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_name\u001b[39m\u001b[38;5;124m\"\u001b[39m: run_name,\n\u001b[1;32m    376\u001b[0m }\n\u001b[0;32m--> 378\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    379\u001b[0m \u001b[43m    \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    380\u001b[0m \u001b[43m    \u001b[49m\u001b[43mcast\u001b[49m\u001b[43m(\u001b[49m\u001b[43mRunnableConfig\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\u001b[43mk\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mv\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mk\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mv\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mconfig\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mv\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mis\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mnot\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    381\u001b[0m \u001b[43m    \u001b[49m\u001b[43mreturn_only_outputs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mreturn_only_outputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    382\u001b[0m \u001b[43m    \u001b[49m\u001b[43minclude_run_info\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minclude_run_info\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    383\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain/chains/base.py:163\u001b[0m, in \u001b[0;36mChain.invoke\u001b[0;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[1;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    162\u001b[0m     run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 163\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m    164\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m    166\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m include_run_info:\n",
      "File \u001b[0;32m~/anaconda3/envs/langchain/lib/python3.10/site-packages/langchain/chains/base.py:155\u001b[0m, in \u001b[0;36mChain.invoke\u001b[0;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[1;32m    150\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    151\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_inputs(inputs)\n\u001b[1;32m    152\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m    153\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs, run_manager\u001b[38;5;241m=\u001b[39mrun_manager)\n\u001b[1;32m    154\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[0;32m--> 155\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    156\u001b[0m     )\n\u001b[1;32m    158\u001b[0m     final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[1;32m    159\u001b[0m         inputs, outputs, return_only_outputs\n\u001b[1;32m    160\u001b[0m     )\n\u001b[1;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "Cell \u001b[0;32mIn[10], line 55\u001b[0m, in \u001b[0;36mBabyAGI._call\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m     52\u001b[0m task \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtask_list\u001b[38;5;241m.\u001b[39mpopleft()\n\u001b[1;32m     54\u001b[0m \u001b[38;5;66;03m# 第二步：执行任务\u001b[39;00m\n\u001b[0;32m---> 55\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mexecute_task\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m     56\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvectorstore\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     57\u001b[0m \u001b[43m    \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexecution_chain\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     58\u001b[0m \u001b[43m    \u001b[49m\u001b[43mobjective\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m     59\u001b[0m \u001b[43m    \u001b[49m\u001b[43mtask\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtask_name\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\n\u001b[1;32m     60\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     61\u001b[0m this_task_id \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mint\u001b[39m(task[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtask_id\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m     62\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprint_task_result(result)\n",
      "Cell \u001b[0;32mIn[9], line 58\u001b[0m, in \u001b[0;36mexecute_task\u001b[0;34m(vectorstore, execution_chain, objective, task, k)\u001b[0m\n\u001b[1;32m     57\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mexecute_task\u001b[39m(vectorstore,execution_chain:LLMChain,objective:\u001b[38;5;28mstr\u001b[39m,task:\u001b[38;5;28mstr\u001b[39m,k:\u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m5\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28mstr\u001b[39m:\n\u001b[0;32m---> 58\u001b[0m     context \u001b[38;5;241m=\u001b[39m \u001b[43m_get_top_tasks\u001b[49m\u001b[43m(\u001b[49m\u001b[43mvectorstore\u001b[49m\u001b[43m,\u001b[49m\u001b[43mquery\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mobjective\u001b[49m\u001b[43m,\u001b[49m\u001b[43mk\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mk\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m     59\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m execution_chain\u001b[38;5;241m.\u001b[39mrun(\n\u001b[1;32m     60\u001b[0m         objective \u001b[38;5;241m=\u001b[39m objective,\n\u001b[1;32m     61\u001b[0m         context \u001b[38;5;241m=\u001b[39m context,\n\u001b[1;32m     62\u001b[0m         task \u001b[38;5;241m=\u001b[39m task\n\u001b[1;32m     63\u001b[0m     )\n",
      "Cell \u001b[0;32mIn[9], line 54\u001b[0m, in \u001b[0;36m_get_top_tasks\u001b[0;34m(vectorstore, query, k)\u001b[0m\n\u001b[1;32m     50\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m []\n\u001b[1;32m     52\u001b[0m sorted_results,_ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mzip\u001b[39m(\u001b[38;5;241m*\u001b[39m\u001b[38;5;28msorted\u001b[39m(results,key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m x:x[\u001b[38;5;241m1\u001b[39m],reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m))\n\u001b[0;32m---> 54\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m [\u001b[38;5;28mstr\u001b[39m(item\u001b[38;5;241m.\u001b[39mmetadata[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mtask\u001b[39m\u001b[38;5;124m'\u001b[39m]) \u001b[38;5;28;01mfor\u001b[39;00m item \u001b[38;5;129;01min\u001b[39;00m sorted_results]\n",
      "Cell \u001b[0;32mIn[9], line 54\u001b[0m, in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m     50\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m []\n\u001b[1;32m     52\u001b[0m sorted_results,_ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mzip\u001b[39m(\u001b[38;5;241m*\u001b[39m\u001b[38;5;28msorted\u001b[39m(results,key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m x:x[\u001b[38;5;241m1\u001b[39m],reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m))\n\u001b[0;32m---> 54\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m [\u001b[38;5;28mstr\u001b[39m(\u001b[43mitem\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmetadata\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtask\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m) \u001b[38;5;28;01mfor\u001b[39;00m item \u001b[38;5;129;01min\u001b[39;00m sorted_results]\n",
      "\u001b[0;31mKeyError\u001b[0m: 'task'"
     ]
    }
   ],
   "source": [
    "baby_agi({\"objective\":OBJECTIVE})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
